package asf.sections
{
	import asf.core.Application;
	import asf.events.ApplicationLoadProgressEvent;
	import asf.events.TransitionEvent;
	import asf.interfaces.ISectionManagement;
	import asf.interfaces.ITransition;
	import asf.transitions.Transition;
	import asf.views.View;

	public class DefaultSectionManager implements ISectionManagement
	{
		protected var app:Application;
		protected var nextTransition:ITransition;
		protected var nextTransitionOut:ITransition;
		protected var nextSection:Section;
		protected var nextInitObject:Object;
		protected var previousSection:Section;
		
		protected var currentSection:Section;
		protected var currentSectionView:View;
		
		protected var currentLoadingSection:Section;
		
		protected var trans:Transition;
		
		public function DefaultSectionManager( p_app:Application )
		{
			app = p_app;
		}
		
		public function dispose( ):void
		{
			if( nextTransition ) nextTransition.dispose( );
			closeCurrentSection( );
			
			currentSectionView = null;
			nextSection = null;
			nextInitObject = null;
			trans = null;
		}
		
		public function changeTo( p_section:*, p_transition:ITransition, p_transitionOut:ITransition = null, p_initObject:Object = null ):Section
		{
			var section:Section;
			
			if( p_section is String ) p_section = app.navigation.getSectionByID( p_section );
			
			if( currentSection ) previousSection = currentSection;
			
			nextSection = p_section;
			nextInitObject = p_initObject;
			nextTransition = p_transition;
			nextTransitionOut = p_transitionOut;
			
			if( nextTransitionOut != null )
			{
				disposeTrans( );
				
				trans = new Transition( null, currentSectionView, app, nextTransitionOut );
				
				trans.addEventListener( TransitionEvent.TRANSITION_START, transitionOutStart );
				trans.addEventListener( TransitionEvent.TRANSITION_COMPLETE, transitionOutComplete );
				
				trans.init( );
			}
			else
			{
				doChangeInit( );
			}
			
			return nextSection;
		}
		
		protected function transitionOutStart( evt:TransitionEvent ):void
		{
			
		}
		
		protected function transitionOutComplete( evt:TransitionEvent ):void
		{
			disposePrevious( );
			doChangeInit( );
		}
		
		protected function doChangeInit( ):void
		{
			if( currentLoadingSection && currentLoadingSection.isLoading )
			{
				currentLoadingSection.removeEventListener( ApplicationLoadProgressEvent.DEPENDENCIES_LOAD_COMPLETE, onComplete );
				currentLoadingSection.stopLoading( );
				
				currentLoadingSection = null;
			}
			
			if( nextSection.isLoaded )
			{
				change( );
			}
			else
			{
				load( );
			}
		}
		
		protected function change( ):void
		{
			var ViewClass:Class = nextSection.viewClass;
			var view:View = new ViewClass( nextSection ) as View;
			
			currentLoadingSection = null;
			
			copyInitAttributes( view, nextInitObject );
			
			nextSection.view = view;
			currentSection = nextSection;
			
			disposeTrans( );
			
			trans = new Transition( view, currentSectionView, app, nextTransition );
			
			trans.addEventListener( TransitionEvent.TRANSITION_START, transitionStartHandler );
			trans.addEventListener( TransitionEvent.TRANSITION_COMPLETE, transitionCompleteHandler );
			
			trans.init( );
			
			currentSectionView = view;
		}
		
		protected function copyInitAttributes( view:Object, initObject:Object ):void
		{
			var key:String;
			if( initObject == null ) return;
			
			for( key in initObject )
			{
				view[ key ] = initObject[ key ];
			}
		}
		
		protected function transitionStartHandler( evt:TransitionEvent ):void
		{
			trans.nextView.baseLayer.addChild( trans.nextView );
		}
		
		protected function transitionCompleteHandler( evt:TransitionEvent ):void
		{
			disposePrevious( );
			disposeTrans( );
		}
		
		protected function disposePrevious( ):void
		{
			if( previousSection )
			{
				var view:View = previousSection.view;
				
				if( view.baseLayer && view.baseLayer.contains( view ) )
				{
					view.baseLayer.removeChild( view );
				}
				
				view.dispose( );
			}
			
			previousSection = null;
		}
		
		public function closeCurrentSection( ):void
		{
			if( currentSection && currentSectionView )
			{
				if( currentSectionView.baseLayer.contains( currentSectionView ) )
				{
					currentSectionView.baseLayer.removeChild( currentSectionView );
				}
				
				currentSectionView.dispose( );
				currentSectionView = null;
			}
			
			disposeTrans( );
			
			currentSection = null;
		}
		
		protected function disposeTrans( ):void
		{
			if( trans )
			{
				trans.dispose( );
				
				trans.removeEventListener( TransitionEvent.TRANSITION_START, transitionStartHandler );
				trans.removeEventListener( TransitionEvent.TRANSITION_COMPLETE, transitionCompleteHandler );
				
				trans = null;
			}
		}
		
		protected function load( ):void
		{
			currentLoadingSection = nextSection;
			
			nextSection.addEventListener( ApplicationLoadProgressEvent.DEPENDENCIES_LOAD_COMPLETE, onComplete );
			nextSection.load( );
		}
		
		protected function onComplete( evt:ApplicationLoadProgressEvent ):void
		{
			nextSection.removeEventListener( ApplicationLoadProgressEvent.DEPENDENCIES_LOAD_COMPLETE, onComplete );
			change( );
		}
		
		public function getCurrentSection( ):Section
		{
			return currentSection;
		}
	}
}